namespace BM.Tools.WebControls.MForm.Generator
{
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    using System.Xml.Schema;

    using BM.Tools.Xml.Schema;

    /// <summary>
    /// FormVisited is a base class for all visited objects in the <see cref="FormBuilder" />.
    /// </summary>
    public class FormVisited : IVisited
    {
        private List<FormVisited> children = new List<FormVisited>();

        private Collection<FormItem> childrenItems;

        /// <summary>
        /// Initializes a new instance of the <see cref="FormVisited"/> class. 
        /// </summary>
        /// <param name="builder">
        /// The builder.
        /// </param>
        /// <param name="parent">
        /// The parent.
        /// </param>
        /// <param name="schemaObject">
        /// The schemaObject.
        /// </param>
        public FormVisited(FormBuilder builder, FormVisited parent, XmlSchemaObject schemaObject)
        {
            Builder = builder;
            Parent = parent;
            if (parent != null)
            {
                Parent.children.Add(this);
            }

            SchemaObject = schemaObject;
        }

        /// <summary>
        /// Gets Builder.
        /// </summary>
        /// <value>
        /// The builder.
        /// </value>
        public FormBuilder Builder
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets ChildrenItems.
        /// </summary>
        /// <value>
        /// The children items.
        /// </value>
        public virtual Collection<FormItem> ChildrenItems
        {
            get
            {
                if (childrenItems == null)
                {
                    CalculateChildrenItems();
                }

                return childrenItems;
            }
        }

        /// <summary>
        /// Gets FormItem.
        /// </summary>
        /// <value>
        /// The form item.
        /// </value>
        public FormItem FormItem
        {
            get
            {
                var item = this as FormItem;
                if (item != null)
                {
                    return item;
                }

                return Parent.FormItem;
            }
        }

        IVisited IVisited.Parent
        {
            get
            {
                return Parent;
            }
        }

        /// <summary>
        /// Gets the visted item parent.
        /// </summary>
        public FormVisited Parent
        {
            get; 
            private set;
        }

        IEnumerable<IVisited> IVisited.Children
        {
            get
            {
                return Children.Cast<IVisited>();
            }
        }

        /// <summary>
        /// Gets the visited item children.
        /// </summary>
        public IEnumerable<FormVisited> Children
        {
            get
            {
                return new ReadOnlyCollection<FormVisited>(children);
            }
        }

        /// <summary>
        /// Gets the visited schema object.
        /// </summary>
        public XmlSchemaObject SchemaObject
        {
            get; 
            private set;
        }

        /// <summary>
        /// Searches for all those children that are of <see cref="FormItem" /> type
        /// </summary>
        internal void CalculateChildrenItems()
        {
            childrenItems = new Collection<FormItem>();
            foreach (FormItem fi in this.GetChildren<FormItem>())
            {
                childrenItems.Add(fi);
            }
        }
    }
}